package com.fg.security;
import java.io.InputStream;
import java.security.Key;
import java.util.Properties;

import javax.crypto.Cipher;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESKeySpec;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

/**
 * Encrypt/Decrypt Class
 * @author jeong-yeonla
 *
 */
public class LocalEncrypter {
	private static final String DES = "DES";
	private static final String TRIPLE_DES = "DESede";
	private static final String PROPERTIES_NAME = "properties/key.properties";
	
	private static String algorithm = DES;
	
	private static Key key = null;
	private static Cipher cipher = null;
	private static String keyString;

	/**
	 * 키와 암호화 형식을 셋팅한다.
	 * @throws Exception
	 */
	private static void setUp() throws Exception {
		keyString = getKeyString_inProperties(PROPERTIES_NAME, algorithm);
		key = getKey(keyString);
		cipher = Cipher.getInstance(algorithm);
	}
	
	/**
	 * Properties 파일안에 있는 것으로부터 key를 읽어온다.
	 * @param fileName Properties파일 이름 
	 * @return DES key String
	 * @throws Exception
	 */
	private static String getKeyString_inProperties(String propertiesName, String desType) throws Exception {
		InputStream in = LocalEncrypter.class.getClassLoader().getResourceAsStream(propertiesName);
		Properties properties = new Properties();
		properties.load(in);
		return properties.getProperty(desType);
	}
	
 
	/**
	 * DES 키를 만들어준다.
	 * @param keyString 문자열 키 
	 * @return DES key객체. 
	 * @throws Exception
	 */
	private static Key getKey(String keyString) throws Exception {
		DESKeySpec desKeySpec = new DESKeySpec(keyString.getBytes());
		SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(algorithm);
		Key key = keyFactory.generateSecret(desKeySpec);
		return key;
	}

	/**
	 * 테스트 메인 메소드임. 삭제요망 
	 * @param args
	 *   * @throws Exception
	 */
	public static void main(String[] args) throws Exception {
		String before = "79";
		String enString = encrypt(before);
		
		System.out.println("before is " + before);
		System.out.println("encrypt is " + enString);
		System.out.println("decrypt is " + decrypt(enString));
	}

	/**
	 * Encrypt string value.
	 * 매번 이 메소드를 수행시킬 때 마다 key값이 재설정된다.
	 * @param input source string
	 * @return encrypted string
	 * @throws Exception
	 */
	public static String encrypt(String input) throws Exception {
		if (input == null)
			return null;
		
		setUp();
	     
		cipher.init(Cipher.ENCRYPT_MODE, key);
	    byte[] inputBytes = input.getBytes("UTF-8");
	    byte[] outputBytes = cipher.doFinal(inputBytes);
	    BASE64Encoder encoder = new BASE64Encoder();
	     
	    String encryptionString = encoder.encode(outputBytes); 
	    return encryptionString;
	}
	
	/**
	 * Decrypt string value.
	 * @param encryptionString source string
	 * @return decrypted string
	 * @throws Exception
	 */
	public static String decrypt(String encryptionString) throws Exception {
		if (encryptionString == null)
			return null;
		
		setUp();
		
	    cipher.init(Cipher.DECRYPT_MODE, key);
	    BASE64Decoder decoder = new BASE64Decoder();
	    byte[] encryptionBytes = decoder.decodeBuffer(encryptionString);
	    byte[] recoveredBytes = cipher.doFinal(encryptionBytes);
	     
	    String recovered = new String(recoveredBytes, "UTF-8");
	    return recovered;
	}
}